package org.wx.thread.unsafe;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * @description: unsafe cas 原子性操作
 * @author: wangxun
 * @createDate: 2021/4/14
 * @version: 1.0
 */
@Data
@Slf4j
public class UnSafeCasTest {
    private volatile int id;
    static Unsafe unsafe;
    static {

        try {
            final Field theUnsafe = Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            unsafe = (Unsafe) theUnsafe.get(null);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        final UnSafeCasTest casTest = new UnSafeCasTest();
        casTest.setId(123);
        final Thread t1 = new Thread(getTarget(casTest), "t1");

        final Thread t2 = new Thread(getTarget(casTest), "t2");

        final Thread t3 = new Thread(getTarget(casTest), "t3");

        t1.start();
        t2.start();
        t3.start();

        try {
            t1.join();
            t2.join();
            t3.join();
        } catch (InterruptedException e) {
            log.error("中断标记位被赋值 消息:{}", e.getMessage());
        }finally {
            log.info("id 最后的值:{}",casTest.getId());
        }


    }

    private static Runnable getTarget(UnSafeCasTest casTest) {
        return () -> {
            for (; ; ) {
                int id = casTest.getId();
                if (unsafe.compareAndSwapInt(casTest, 12L, id, id + 1)) {
                    log.info("{} cas成功 修改前的值{} 修改后的值{}", Thread.currentThread().getName(),id, casTest.getId());
                    break;
                }
                log.info("{} 失败", Thread.currentThread().getName());
            }

        };
    }
}
